﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Net;
using System.Security.Policy;
using System.Text;
using System.Threading.Tasks;
using System.Xml;

namespace AutoUpdater
{
    public class UpdateManager
    {
        private string configFile = "UpdateConfig.xml";
        private string tempDownloadPath = Path.GetTempPath();

        public RemoteVersionInfo RemoteVersionInfo { get; private set; }
        public event Action<int, string> DownloadProgressChanged;

        public async Task<bool> CheckForUpdatesAsync()
        {
            return await Task.Run(() =>
            {
                try
                {
                    XmlDocument configDoc = new XmlDocument();
                    configDoc.Load(configFile);

                    string localVersion = configDoc.SelectSingleNode("//LocalVersion")?.InnerText;
                    string userName = configDoc.SelectSingleNode("//GitCodeConfig/UserName")?.InnerText;
                    string projectName = configDoc.SelectSingleNode("//GitCodeConfig/ProjectName")?.InnerText;
                    string branch = configDoc.SelectSingleNode("//GitCodeConfig/Branch")?.InnerText ?? "main";
                    string versionFilePath = configDoc.SelectSingleNode("//GitCodeConfig/VersionFilePath")?.InnerText;



            
                    string versionFileUrl = $"https://gitee.com/{userName}/{projectName}/raw/{branch}/AutoUpdater/bin/Debug/net8.0-windows/{versionFilePath}";
                    RemoteVersionInfo = GetRemoteVersionInfo(versionFileUrl);

                    return RemoteVersionInfo.Version != localVersion;
                }
                catch (Exception ex)
                {
                    throw new Exception($"检查更新失败: {ex.Message}");
                }
            });
        }

        public string GetUpdateSummary()
        {
            if (RemoteVersionInfo == null) return string.Empty;

            var summary = $"版本: {RemoteVersionInfo.Version}\n" +
                         $"发布日期: {RemoteVersionInfo.ReleaseDate}\n" +
                         $"更新标题: {RemoteVersionInfo.Title}\n" +
                         $"更新描述: {RemoteVersionInfo.Description}\n" +
                         "更新内容:\n";

            foreach (var change in RemoteVersionInfo.Changes)
            {
                summary += $"  • {change}\n";
            }

            return summary;
        }

        public void DownloadUpdate()
        {
            try
            {
                XmlDocument configDoc = new XmlDocument();
                configDoc.Load(configFile);
                string userName = configDoc.SelectSingleNode("//GitCodeConfig/UserName")?.InnerText;
                string projectName = configDoc.SelectSingleNode("//GitCodeConfig/ProjectName")?.InnerText;
                string branch = configDoc.SelectSingleNode("//GitCodeConfig/Branch")?.InnerText ?? "main";
                string updatePackageName = configDoc.SelectSingleNode("//GitCodeConfig/UpdatePackageName")?.InnerText;
                string updatePackageUrl = $"https://gitee.com/{userName}/{projectName}/raw/{RemoteVersionInfo.Tonke}/AutoUpdater/bin/Debug/net8.0-windows/{updatePackageName}";
                string downloadedZipPath = Path.Combine(tempDownloadPath, updatePackageName);
                using (WebClient client = new WebClient())
                {
                    client.DownloadProgressChanged += (s, e) =>
                    {
                        DownloadProgressChanged?.Invoke(e.ProgressPercentage, $"下载进度: {e.ProgressPercentage}%");
                    };

                    client.DownloadFile(updatePackageUrl, downloadedZipPath);
                }
            }
            catch (Exception ex)
            {
                throw new Exception($"下载更新包失败: {ex.Message}");
            }
        }

        public void BackupApplication()
        {
            try
            {
                XmlDocument configDoc = new XmlDocument();
                configDoc.Load(configFile);
                string backupDir = configDoc.SelectSingleNode("//ApplicationInfo/BackupDir")?.InnerText;

                if (!Directory.Exists(backupDir))
                {
                    Directory.CreateDirectory(backupDir);
                }

                string currentDir = Directory.GetCurrentDirectory();
                string[] excludeExtensions = { ".zip", ".tmp", ".log" };
                string[] excludeFiles = { configFile };

                foreach (string file in Directory.GetFiles(currentDir))
                {
                    string fileName = Path.GetFileName(file);
                    bool shouldExclude = false;

                    foreach (string excludeFile in excludeFiles)
                    {
                        if (fileName.Equals(excludeFile, StringComparison.OrdinalIgnoreCase))
                        {
                            shouldExclude = true;
                            break;
                        }
                    }

                    if (!shouldExclude)
                    {
                        string extension = Path.GetExtension(file);
                        foreach (string excludeExt in excludeExtensions)
                        {
                            if (extension.Equals(excludeExt, StringComparison.OrdinalIgnoreCase))
                            {
                                shouldExclude = true;
                                break;
                            }
                        }
                    }

                    if (!shouldExclude)
                    {
                        string destFile = Path.Combine(backupDir, fileName);
                        File.Copy(file, destFile, true);
                    }
                }
            }
            catch (Exception ex)
            {
                throw new Exception($"备份应用程序失败: {ex.Message}");
            }
        }

        public void ApplyUpdate()
        {
            try
            {
                XmlDocument configDoc = new XmlDocument();
                configDoc.Load(configFile);
                string updatePackageName = configDoc.SelectSingleNode("//GitCodeConfig/UpdatePackageName")?.InnerText;
                string zipPath = Path.Combine(tempDownloadPath, updatePackageName);

                if (!File.Exists(zipPath))
                {
                    throw new FileNotFoundException("更新包文件不存在");
                }

                // 解压到临时目录，而不是当前目录
                string tempExtractPath = Path.Combine(Path.GetTempPath(), "AutoUpdater_Temp");
                if (Directory.Exists(tempExtractPath))
                {
                    Directory.Delete(tempExtractPath, true);
                }

                ZipFile.ExtractToDirectory(zipPath, tempExtractPath, overwriteFiles: true);
                File.Delete(zipPath);

                // 创建更新脚本
                CreateUpdateScript(tempExtractPath);

                // 启动更新程序并退出当前程序
                StartUpdaterAndExit();
            }
            catch (Exception ex)
            {
                throw new Exception($"应用更新失败: {ex.Message}");
            }
        }

        private void CreateUpdateScript(string tempExtractPath)
        {
            string currentDir = Directory.GetCurrentDirectory();
            string updaterScript = Path.Combine(Path.GetTempPath(), "apply_update.bat");

            string scriptContent = $@"
@echo off
chcp 65001 >nul
echo 正在应用更新，请稍候...
timeout /t 2 /nobreak >nul

:: 等待主程序退出
:WaitLoop
tasklist /fi ""Imagename eq AutoUpdater.exe"" | find /i ""AutoUpdater.exe"" >nul
if not errorlevel 1 (
    timeout /t 1 /nobreak >nul
    goto WaitLoop
)

:: 复制文件
xcopy ""{tempExtractPath}\*"" ""{currentDir}"" /y /e /q

:: 清理临时文件
rmdir /s /q ""{tempExtractPath}""
del ""{updaterScript}""

:: 重启应用程序
start """" ""{Path.Combine(currentDir, "AutoUpdater.exe")}""
";

            File.WriteAllText(updaterScript, scriptContent, Encoding.UTF8);
        }

        private void StartUpdaterAndExit()
        {
            string updaterScript = Path.Combine(Path.GetTempPath(), "apply_update.bat");

            ProcessStartInfo startInfo = new ProcessStartInfo
            {
                FileName = "cmd.exe",
                Arguments = $"/c \"{updaterScript}\"",
                WindowStyle = ProcessWindowStyle.Hidden,
                UseShellExecute = true
            };

            Process.Start(startInfo);
            Application.Exit();
        }

        public void UpdateLocalVersion()
        {
            try
            {
                XmlDocument configDoc = new XmlDocument();
                configDoc.Load(configFile);

                XmlNode localVersionNode = configDoc.SelectSingleNode("//LocalVersion");
                if (localVersionNode != null && RemoteVersionInfo != null)
                {
                    localVersionNode.InnerText = RemoteVersionInfo.Version;
                    configDoc.Save(configFile);
                }

                // 更新版本信息
                UpdateLocalVersionInfo(configDoc, RemoteVersionInfo);
            }
            catch (Exception ex)
            {
                throw new Exception($"更新本地版本号失败: {ex.Message}");
            }
        }

        private RemoteVersionInfo GetRemoteVersionInfo(string versionFileUrl)
        {
            try
            {
                using (WebClient client = new WebClient())
                {
                    string versionContent = client.DownloadString(versionFileUrl);
                    var versionInfo = new RemoteVersionInfo();

                    using (StringReader reader = new StringReader(versionContent))
                    {
                        string line;
                        while ((line = reader.ReadLine()) != null)
                        {
                            if (line.StartsWith("version="))
                                versionInfo.Version = line.Substring(8);
                            else if (line.StartsWith("release_date="))
                                versionInfo.ReleaseDate = line.Substring(13);
                            else if (line.StartsWith("title="))
                                versionInfo.Title = line.Substring(6);
                            else if (line.StartsWith("description="))
                                versionInfo.Description = line.Substring(12);
                            else if (line.StartsWith("tonke"))
                            {
                                versionInfo.Tonke = line.Substring(40);
                            }
                            else if (line.StartsWith("changes="))
                            {
                                string changes = line.Substring(8);
                                versionInfo.Changes = new List<string>(changes.Split(';'));
                            }
                          

                        }
                    }

                    return versionInfo;
                }
            }
            catch (WebException ex)
            {
                throw new Exception($"无法获取远程版本信息: {ex.Message}");
            }
        }

        private void UpdateLocalVersionInfo(XmlDocument configDoc, RemoteVersionInfo versionInfo)
        {
            try
            {
                XmlNode latestVersionNode = configDoc.SelectSingleNode("//UpdateInfo/LatestVersion");
                XmlNode releaseDateNode = configDoc.SelectSingleNode("//UpdateInfo/ReleaseDate");
                XmlNode updateTitleNode = configDoc.SelectSingleNode("//UpdateInfo/UpdateTitle");
                XmlNode updateDescriptionNode = configDoc.SelectSingleNode("//UpdateInfo/UpdateDescription");
                XmlNode changeLogNode = configDoc.SelectSingleNode("//UpdateInfo/ChangeLog");

                if (latestVersionNode != null) latestVersionNode.InnerText = versionInfo.Version;
                if (releaseDateNode != null) releaseDateNode.InnerText = versionInfo.ReleaseDate;
                if (updateTitleNode != null) updateTitleNode.InnerText = versionInfo.Title;
                if (updateDescriptionNode != null) updateDescriptionNode.InnerText = versionInfo.Description;

                if (changeLogNode != null)
                {
                    changeLogNode.RemoveAll();
                    foreach (var change in versionInfo.Changes)
                    {
                        XmlElement changeElement = configDoc.CreateElement("Change");
                        changeElement.InnerText = change;
                        changeLogNode.AppendChild(changeElement);
                    }
                }

                configDoc.Save(configFile);
            }
            catch (Exception)
            {
                // 忽略版本信息更新错误
            }
        }
    }

    public class RemoteVersionInfo
    {
        public string Version { get; set; } = "1.0.0";
        public string ReleaseDate { get; set; } = DateTime.Now.ToString("yyyy-MM-dd");
        public string Tonke { get; set; } = "";
        public string Title { get; set; } = "更新";
        public string Description { get; set; } = "常规更新";
        public List<string> Changes { get; set; } = new List<string>();
    }
}